package com.saohuobang.test.service;

import com.github.dreamhead.moco.HttpServer;
import com.github.dreamhead.moco.Runner;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.saohuobang.test.listener.PropertyFileListener;
import com.saohuobang.test.model.BusinessInfo;
import com.saohuobang.test.model.UnitProperty;
import com.saohuobang.test.model.core.SystemException;
import com.saohuobang.test.model.enums.ContentTypeEnum;
import com.saohuobang.test.util.AppConfig;
import com.saohuobang.test.util.PropertyUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;

import static com.github.dreamhead.moco.Moco.*;
import static com.github.dreamhead.moco.Runner.runner;

/**
 * 作者 yaohua.liu
 * 日期 2015-12-11 17:57
 * 说明 ...
 */
@Service
public class FrameworkService {

    private final Logger logger = LoggerFactory.getLogger(FrameworkService.class);

    private String properties_root_dir = /*"/home/liuyaohua/properties_root_dir";*/AppConfig.getString("properties_root_dir");

    private Map<Integer, Runner> runnerMap = Maps.newConcurrentMap();

    // load properties
    private List<BusinessInfo> businessInfos = null;
    // 配置文件监听器
    private PropertyFileListener propertyFileListener = PropertyFileListener.getInstance();

    public FrameworkService() {
        start();
    }

    public List<BusinessInfo> loadProperties() throws SystemException {
        List<BusinessInfo> businessInfos = PropertyUtil.checkRootDirPath(properties_root_dir);
        if (businessInfos == null || businessInfos.size() == 0) {
            logger.warn("properties is null,dir path = {}", properties_root_dir);
            return null;
        }
        return PropertyUtil.loadBusinessProperties(businessInfos);
    }

    private Runner createRunner(int port, String dataDirRootPath, List<UnitProperty> properties) {
        int temPort = AppConfig.getInt("JETTY_PORT");
        if (port == temPort) {
            logger.error("port:{},与系统Port:{}冲突", port, temPort);
            return null;
        }
        HttpServer server = httpServer(port);
        for (UnitProperty property : properties) {
            String dataPath = dataDirRootPath + "/data/" + property.getFileName() + "." + property.getFileType();
            /*String data = null;
            try {
                //data = file(new File(dataPath), Charset.forName(property.getCharset()));
                data = Files.toString(new File(dataPath), Charset.forName(property.getCharset()));
            } catch (IOException e) {
                logger.error("获取data出现异常：msg = {}", e.getMessage(), e);
                continue;
            }*/
            server.request(and(by(uri(property.getUri())), by(method(property.getHttpMethod()))/*, by(version("1.0"))*/)).response(with(file(dataPath, Charset.forName(property.getCharset()))/*text(data)*/), header("Content-Type", ContentTypeEnum.getDescByName(property.getFileType())+";charset="+property.getCharset()));
            logger.info("start server,port = {},method = {},uri = {}, property file = {}", port, property.getHttpMethod(), property.getUri(), dataPath);
        }
        Runner runner = runner(server);
        runner.start();
        return runner;
    }

    public List<BusinessInfo> start() {
        try {
            businessInfos = loadProperties();
        } catch (SystemException e) {
            return Lists.newArrayList();
        }
        // start server
        for (BusinessInfo businessInfo : businessInfos) {
            Runner runner = createRunner(businessInfo.getPort(), businessInfo.getRootDir(), businessInfo.getProperties());
            if (runner == null) {
                continue;
            }
            runnerMap.put(businessInfo.getPort(), runner);
        }
        propertyFileListener.setFrameworkService(this);
        propertyFileListener.startMonitor(PropertyUtil.businessToString(properties_root_dir,businessInfos));
        return businessInfos;
    }

    public int stop() {
        if (runnerMap == null || runnerMap.size() == 0) {
            return 0;
        }
        int i = 0;
        for (Runner runner : runnerMap.values()) {
            if (runner != null) {
                ++i;
                runner.stop();
            }
        }
        return i;
    }

    public List<BusinessInfo> restart() {
        stop();
        return start();
    }

    public List<BusinessInfo> getBusinessInfos() {
        return businessInfos;
    }
}
